package net.jescort.seurity.shiro;

import com.google.common.collect.Lists;
import com.google.gson.GsonBuilder;
import net.gelif.modules.memcached.MemcachedObjectType;
import net.gelif.modules.memcached.SpyMemcachedClient;
import net.jescort.domain.user.User;
import net.jescort.persistence.dao.UserDao;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.shiro.SecurityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * Created by IntelliJ IDEA.
 * User: Administrator
 * Date: 11-7-7
 * Time: 上午8:07
 * To change this template use File | Settings | File Templates.
 */
public class AccountManager
{
    private static Logger logger = LoggerFactory.getLogger(AccountManager.class);

    private UserDao userDao;

    private SpyMemcachedClient memcachedClient;

    /**
     * 在保存用户时,发送用户修改通知消息, 由消息接收者异步进行较为耗时的通知邮件发送.
     * <p/>
     * 如果企图修改超级用户,取出当前操作员用户,打印其信息然后抛出异常.
     */
    //演示指定非默认名称的TransactionManager.
    @Transactional
    public void saveUser(User user)
    {

        if (isSupervisor(user))
        {
            logger.warn("操作员{}尝试修改超级管理员用户", SecurityUtils.getSubject().getPrincipal());
            throw new RuntimeException("不能修改超级管理员用户");
        }

        String password = DigestUtils.shaHex(user.getPassword());
        user.setPassword(password);

        userDao.save(user);
    }

    /**
     * 判断是否超级管理员.
     */
    private boolean isSupervisor(User user)
    {
        return (user.getId() != null && user.getId() == 1L);
    }

    @Transactional(readOnly = true)
    public User getUser(Integer id)
    {
        return userDao.findOne(id);
    }

    /**
     * 取得用户, 并对用户的延迟加载关联进行初始化.
     */
    @Transactional(readOnly = true)
    public User getInitializedUser(Integer id)
    {
        if (memcachedClient != null)
        {
            return getUserFromMemcached(id);
        } else
        {
            return userDao.findOne(id);
        }
    }

    /**
     * 访问Memcached, 使用JSON字符串存放对象以节约空间.
     */
    private User getUserFromMemcached(Integer id)
    {

        String key = MemcachedObjectType.USER.getPrefix() + id;

        User user = null;
        String jsonString = memcachedClient.get(key);

        if (jsonString == null)
        {
            //用户不在 memcached中,从数据库中取出并放入memcached.
            //因为hibernate的proxy问题多多,此处使用jdbc
            user = userDao.findOne(id);
            if (user != null)
            {
                jsonString = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create().toJson(user);
                memcachedClient.set(key, MemcachedObjectType.USER.getExpiredTime(), jsonString);
            }
        } else
        {
            user = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create().fromJson(jsonString, User.class);
        }
        return user;
    }

    /**
     * 按名称查询用户, 并对用户的延迟加载关联进行初始化.
     */
    @Transactional(readOnly = true)
    public User searchInitializedUserByName(String username)
    {
        User user = userDao.findByUsername(username);
        return user;
    }

    /**
     * 取得所有用户, 预加载用户的角色.
     */
    @Transactional(readOnly = true)
    public List<User> getAllUserWithRole()
    {
        List<User> list = Lists.newArrayList(userDao.findAll());
        logger.info("findOne {} user sucessful.", list.size());
        return list;
    }

    /**
     * 获取当前用户数量.
     */
    @Transactional(readOnly = true)
    public Long getUserCount()
    {
        return userDao.count();
    }

    @Transactional(readOnly = true)
    public User findUserByUsername(String username)
    {
        return userDao.findByUsername(username);
    }

    public void setUserDao(UserDao userDao)
    {
        this.userDao = userDao;
    }

    public void setMemcachedClient(SpyMemcachedClient memcachedClient)
    {
        this.memcachedClient = memcachedClient;
    }
}
